home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Interactive 4
/
PC World Interactive 4.iso
/
online
/
appbar.EXE
/
cppsrc
/
AppBarWin.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-20
|
14KB
|
517 lines
// *********************************************************
// AppBar -- Advanced Menu bar for Windows 95/NT
// All code Copyright (C) 1995, 1996 by Mike Perham
// mperham@cs.cornell.edu
//
// This code MAY NOT be used for any other program without
// my permission and is forbidden in any shareware/commercial
// program. This code is provided for educational use only
// and there are no guarantees or promises implied. Blah blah
// *********************************************************
//////////////////////////////////////////////////////////////////////////////////
// AppBarWin - the Window
// This file encapsulates all functions that affect what the user sees
// on the screen and all UI elements.
//////////
#include "appbar.h"
#include "globals.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(AppBarWin, CWnd)
//{{AFX_MSG_MAP(AppBarWin)
ON_WM_ACTIVATE()
ON_WM_NCMOUSEMOVE()
ON_WM_NCRBUTTONDOWN()
// ON_WM_NCLBUTTONDBLCLK()
ON_WM_SHOWWINDOW()
ON_WM_TIMECHANGE()
ON_WM_WINDOWPOSCHANGED()
ON_WM_TIMER()
ON_WM_CLOSE()
ON_MESSAGE(WM_HOTKEY, OnHotKey)
ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
ON_MESSAGE(WM_POWERBROADCAST, OnPowerBroadcast)
ON_COMMAND(ID_ABOUT, OnAbout)
ON_COMMAND(ID_EDIT, OnEdit)
ON_COMMAND(ID_OPTIONS, OnOptions)
ON_COMMAND(ID_EXITAPPBAR, OnExit)
ON_COMMAND_RANGE(101, 40000, OnAppSelect)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void inline AppBarWin::ab_message(char *msg)
{
MessageBox(msg, "AppBar", MB_OK | MB_ICONINFORMATION);
}
/////////////////////////////////////////////////////////////////////////////
// AppBarWin message handlers
BOOL AppBarWin::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int width, int height, HWND ParentWnd, HMENU nID, LPVOID pContext)
{
BOOL t = CWnd::CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
x, y, width, height, ParentWnd, nID, pContext);
if (sv.newshell) {
BOOL ab;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = m_hWnd;
abd.uCallbackMessage = NULL;
abd.uEdge = (uv.bottom ? ABE_BOTTOM : ABE_TOP);
ab = SHAppBarMessage(ABM_NEW, &abd);
if (ab && uv.autohide) {
abd.lParam = TRUE;
if (!SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) {
ab_message(ERROR_AUTOHIDING);
uv.autohide = FALSE;
}
} else if (ab) {
abd.rc.top = 0;
abd.rc.left = 0;
abd.rc.right = GetSystemMetrics(SM_CXSCREEN);
abd.rc.bottom = GetSystemMetrics(SM_CYSCREEN);
SHAppBarMessage(ABM_QUERYPOS, &abd);
abd.rc.top = (uv.bottom ? abd.rc.bottom - AB_HEIGHT : abd.rc.top);
MoveWindow(abd.rc.left, abd.rc.top, AB_WIDTH, AB_HEIGHT, FALSE);
abd.rc.bottom = abd.rc.top + AB_HEIGHT;
abd.rc.right = AB_WIDTH;
SHAppBarMessage(ABM_SETPOS, &abd);
}
}
// Insert applications into menu
UpdateMenu();
return t;
}
void AppBarWin::OnEdit()
{
EditDlg ed(this);
ed.DoModal();
}
void AppBarWin::OnAbout()
{
AboutDlg ad;
ad.DoModal();
}
void AppBarWin::OnOptions()
{
OptDlg od;
od.DoModal();
}
void AppBarWin::OnExit()
{
ATOM adam = GlobalFindAtom("AppBar HotKey");
UnregisterHotKey(m_hWnd, adam);
GlobalDeleteAtom(adam);
ab.ExitAppBar(FALSE);
}
void AppBarWin::OnAppSelect(UINT id)
{
app_struct *find = find_appId(id);
ASSERT(find);
ab.ExecuteApplication(find);
}
LONG AppBarWin::OnHotKey(UINT u, LONG l)
{
int bitmask;
HideAppBar(FALSE);
SetForegroundWindow();
// this is the code for pressing the Alt key down
// so we can make the menu highlight
bitmask = 0x00000001 | 38<<16 | 1<<24 | 1<<29;
PostMessage(WM_SYSKEYDOWN, VK_MENU, bitmask);
bitmask = 0x00000001 | 38<<16 | 3<<30;
PostMessage(WM_SYSKEYUP, VK_MENU, bitmask);
return TRUE;
}
void AppBarWin::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CWnd::OnActivate(nState, pWndOther, bMinimized);
if ((nState == WA_INACTIVE) && uv.autohide) {
HideAppBar(TRUE);
KillTimer(HIDE_TIMER);
}
if (sv.newshell) {
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = m_hWnd;
SHAppBarMessage(ABM_ACTIVATE, &abd);
}
}
void AppBarWin::OnNcMouseMove(UINT nFlags, CPoint point)
{
if (uv.autohide)
if (!IsShown) {
POINT pt;
GetCursorPos(&pt);
// Don't show AppBar if the mouse moves in the right 10% of the screen.
// This is so using the max/min buttons doesn't accidently unhide
// AppBar.
if (pt.x < sv.width - (int)(sv.width/10))
HideAppBar(FALSE);
timer = SetTimer(HIDE_TIMER, 500, NULL);
} else {
if (timer)
KillTimer(HIDE_TIMER);
timer = SetTimer(HIDE_TIMER, 500, NULL);
}
CWnd::OnNcMouseMove(nFlags, point);
}
/*
void AppBarWin::OnNcLButtonDblClk(UINT nHitTest, CPoint pt)
{
ATOM adam = GlobalFindAtom("AppBar HotKey");
UnregisterHotKey(m_hWnd, adam);
GlobalDeleteAtom(adam);
ab.ExitAppBar(FALSE);
}
*/
// when AppBar is closed via the Task Manager
void AppBarWin::OnClose()
{
ATOM adam = GlobalFindAtom("AppBar HotKey");
UnregisterHotKey(m_hWnd, adam);
GlobalDeleteAtom(adam);
ab.ExitAppBar(FALSE);
}
void AppBarWin::OnNcRButtonDown(UINT nHitTest, CPoint pt)
{
CWnd::OnNcRButtonDown(nHitTest, pt);
CMenu menu;
VERIFY(menu.LoadMenu(IDR_MENU));
CMenu *Popup = menu.GetSubMenu(0);
ASSERT(Popup);
Popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pt.x, pt.y, AfxGetMainWnd());
}
void AppBarWin::OnShowWindow(BOOL bShow, UINT nStatus)
{
CWnd::OnShowWindow(bShow, nStatus);
if (!RegisterHotKey(m_hWnd, GlobalAddAtom("AppBar HotKey"), MOD_ALT | MOD_CONTROL, 0x5A /*z*/))
if (!RegisterHotKey(m_hWnd, GlobalAddAtom("AppBar HotKey"), MOD_ALT | MOD_CONTROL, 0x41 /*a*/))
ab_message(ERROR_HOTKEY);
IsShown = TRUE;
SyncTime();
}
void AppBarWin::OnTimeChange()
{
ModifyTime();
CWnd::OnTimeChange();
}
void AppBarWin::OnTimer(UINT id)
{
if (id == TIME_UPDATE)
ModifyTime();
else if (id == HIDE_TIMER) {
if (uv.autohide)
if (GetActiveWindow() != this) {
POINT pt;
GetCursorPos(&pt);
if (WindowFromPoint(pt) != this) {
timer = NULL;
KillTimer(HIDE_TIMER);
HideAppBar(TRUE);
}
}
} else if (id == SYNC_TIMER) {
KillTimer(TIME_UPDATE);
KillTimer(SYNC_TIMER);
SetTimer(TIME_UPDATE, 10000, NULL);
ModifyTime();
}
CWnd::OnTimer(id);
}
void AppBarWin::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
CWnd::OnWindowPosChanged(lpwndpos);
if (sv.newshell) {
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = m_hWnd;
SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
}
}
LONG AppBarWin::OnPowerBroadcast(UINT event, LONG data)
{
if (sv.power) {
SYSTEM_POWER_STATUS sps;
GetSystemPowerStatus(&sps);
sv.battery = (sps.ACLineStatus ? FALSE : TRUE);
ModifyTime();
}
return TRUE;
}
LONG AppBarWin::OnDisplayChange(UINT wParam, LONG lParam)
{
if (sv.newshell) {
sv.width = GetSystemMetrics(SM_CXSCREEN);
sv.height = GetSystemMetrics(SM_CYSCREEN);
MoveWindow(0, (uv.bottom ? sv.height - AB_HEIGHT : 0), AB_WIDTH, AB_HEIGHT, TRUE);
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Add-on functions
///////////
// Syncs AppBar's timer with the system time
void AppBarWin::SyncTime(void)
{
SYSTEMTIME st;
GetSystemTime(&st);
// install timer that goes off at next 10 sec interval (10, 20, 30, etc.)
SetTimer(SYNC_TIMER, ((9-(st.wSecond%10))*1000)+(1000-st.wMilliseconds), NULL);
}
///////////////////////////////////////////////////////////////
// Based on function in Microsoft Systems Journal
// March 1996 by Jeffrey Richter
////
void AppBarWin::Slide(int newy)
{
int y, t_start, t_end, t_curr, hide_time;
RECT start;
hide_time = (IsShown ? 300 : 200);
GetWindowRect(&start);
t_start = GetTickCount();
t_end = t_start + hide_time;
// Raise the thread priority so that the slide is smooth rather than jerky
// This is not necessary on a Pentium Pro 200Mhz running NT 4.0 :)
// SetThreadPriority(ab.m_hThread, THREAD_PRIORITY_ABOVE_NORMAL);
while ((t_curr = GetTickCount()) < t_end) {
y = start.top - (start.top - newy) * (int) (t_curr - t_start) / hide_time;
SetWindowPos(NULL, 0, y, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
UpdateWindow();
}
SetWindowPos(NULL, 0, newy, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
UpdateWindow();
// SetThreadPriority(ab.m_hThread, THREAD_PRIORITY_NORMAL);
}
//////////// hides or shows AppBar, depending on "hide" variable
void AppBarWin::HideAppBar(BOOL hide)
{
int newy;
BOOL drag = TRUE;
if (!hide && IsShown)
return;
// if you want AppBar to always slide, just comment out this call
if (sv.newshell)
SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &drag, 0);
if (hide) {
newy = (uv.bottom ? sv.height - 2 : -(AB_HEIGHT - 2));
IsShown = FALSE;
drag ? Slide(newy) : SetWindowPos(NULL, 0, newy, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
} else {
newy = (uv.bottom ? sv.height - AB_HEIGHT : 0);
IsShown = TRUE;
drag ? Slide(newy) : SetWindowPos(NULL, 0, newy, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
ModifyTime();
}
}
//////////////////////////////////////////////////////////////
void AppBarWin::UpdateMenu(void)
{
int a = 1, m = 1; // current app/menu
app_struct *app;
menu_struct *menu, *firstapp; // curr menu/first menu with an app
CMenu hmenu, ab_menu;
app_list *curapplist, *prevapplist;
kill_applist();
ab_menu.CreateMenu();
// empty AppBar ???
if (!glob_menu) {
applist = NULL;
SetMenu(&ab_menu);
ab_menu.Detach();
DrawMenuBar();
return;
}
// find the first non-empty menu
for (menu = glob_menu, firstapp = NULL; menu; menu = menu->nextmenu)
if (menu->nextapp) {
firstapp = menu;
break;
}
for (menu = glob_menu; menu; menu = menu->nextmenu) {
hmenu.CreateMenu();
for (app = menu->nextapp; app; app = app->nextapp) {
if (app->separator) // Put in separator
hmenu.AppendMenu(MF_SEPARATOR, 0, (LPCTSTR)NULL);
hmenu.AppendMenu(MF_STRING, (m*100 + a), app->appname);
if (firstapp->nextapp == app) {
applist = new app_list;
curapplist = applist;
} else {
curapplist = new app_list;
prevapplist->next = curapplist;
}
curapplist->appId = m*100 + a;
curapplist->app = app;
curapplist->next = NULL;
prevapplist = curapplist;
a++;
}
ab_menu.InsertMenu(m, MF_BYPOSITION | MF_POPUP,
(UINT)hmenu.m_hMenu, menu->menuname);
hmenu.Detach();
a = 1;
m++;
}
SetMenu(&ab_menu);
ab_menu.Detach();
DrawMenuBar();
return;
}
// Update time on menubar every minute
void AppBarWin::ModifyTime(void)
{
char string[105] = "";
char time[20] = "";
char date[25] = "";
char mem[10] = "";
char user[40] = "";
char batt[20] = "";
static BOOL played_wav;
SYSTEM_POWER_STATUS sps;
// if AppBar is hiding, why bother drawing?
if (IsShown) {
if (uv.user)
sprintf(user, "%s ", sv.user);
if (uv.time) {
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, NULL,
NULL, time, sizeof(time));
strcat(time, " ");
}
if (uv.date) {
GetDateFormat(LOCALE_SYSTEM_DEFAULT, NULL, NULL, NULL,
date, sizeof(date));
strcat(date, " ");
}
if (uv.memory) {
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
sprintf(mem, "%dk ", (int)ms.dwAvailPhys/1024);
}
if (sv.power)
if (sv.battery) {
GetSystemPowerStatus(&sps);
sprintf(batt, "%d%%", sps.BatteryLifePercent);
if (sps.BatteryLifePercent == 255) // unknown percentage
sprintf(batt, "--%%");
}
// final string to print on AppBar
sprintf(string, "%s%s%s%s%s", user, time, date, mem, batt);
SIZE s;
int x,y;
TEXTMETRIC tm;
COLORREF c;
CFont cf, *oldcf;
NONCLIENTMETRICS ncm;
CWindowDC cdc(this);
if (sv.newshell) {
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
cf.CreateFontIndirect(&(ncm.lfMenuFont));
oldcf = (CFont *) cdc.SelectObject(&cf);
}
c = cdc.SetTextColor(GetSysColor(COLOR_MENUTEXT));
cdc.SetBkColor(GetSysColor(COLOR_MENU));
GetTextExtentPoint32(cdc.m_hDC, string, strlen(string), &s);
x = AB_WIDTH - s.cx - 7;
cdc.GetTextMetrics(&tm);
y = (int) ((AB_HEIGHT - tm.tmHeight) / 2);
// Draw all the stats at (x,y)
DrawMenuBar();
cdc.TextOut(x, y, string, strlen(string));
if (sv.power)
if (sv.battery) {
if (sps.BatteryLifePercent > 25)
cdc.SetTextColor(GREEN);
else if (sps.BatteryLifePercent > 10)
cdc.SetTextColor(YELLOW);
else
cdc.SetTextColor(RED);
GetTextExtentPoint32(cdc.m_hDC, batt, strlen(batt), &s);
x = AB_WIDTH - s.cx - 7;
cdc.TextOut(x, y, batt, strlen(batt));
}
if (sv.newshell) {
cdc.SelectObject(oldcf);
cf.DeleteObject();
}
cdc.SetTextColor(c);
} // end if (IsShown)
if (uv.chime) {
SYSTEMTIME st;
GetSystemTime(&st);
// if it's the top of the hour and we haven't already played this minute...
if ((st.wMinute == 0) && (!played_wav)) {
played_wav = TRUE;
if (!PlaySound(uv.wavfile, NULL, SND_ASYNC | SND_FILENAME))
ab_message(ERROR_PLAYING_WAV);
} else if (st.wMinute == 1)
played_wav = FALSE;
}
}
AppBarWin::AppBarWin()
{
CWnd::CWnd();
}
AppBarWin::~AppBarWin()
{
CWnd::~CWnd();
}